﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using AuchanScan.Datas;
using Newtonsoft.Json.Linq;
using System.ComponentModel;

namespace AuchanScan.Services
{
    public class PromotionService:INotifyPropertyChanged
    {
      
        private const string PROMO_FILE = "promo.json";
        private const string JSON_PROMO_URL = "http://www.rudyhuyn.com/auchan/";

        private static PromotionService _current;
        public static PromotionService Current
        {
            get { return _current ?? (_current = new PromotionService()); }
        }

        public Promotions Promotions { get; set; }

        public void Load()
        {
            var wc = new WebClient();
            wc.OpenReadCompleted += (sender, er) =>
                {
                    if (er.Error != null || er.Cancelled)
                        return;
                    Promotions = LoadPromotions(er.Result);
                    RaisePropertyChanged("Promotions");

                using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream fs = store.OpenFile(PROMO_FILE, FileMode.Create))
                    {
                        try {
                            using (var sw = new StreamWriter(fs)) {
                                sw.Write(er.Result);
                            }
                        }
                        catch (Exception e) {
                            throw e;
                        }
                    }
                }
            };
            wc.OpenReadAsync(new Uri(JSON_PROMO_URL + "/promojson.txt"));
        }

        /// <summary>
        /// Loads a stream promotion file
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static Promotions LoadPromotions(Stream stream)
        {
            var p = new Promotions();
           
            stream.Position = 0;
            var reader = new StreamReader(stream);
            string content = reader.ReadToEnd();
            JObject json = JObject.Parse(content);

            IEnumerable<JToken> items = json["data"].Where(j => j["c"].ToString() == "2" || j["c"].ToString() == "1");
            //Update (2) or Insertion (1)

            #region Tracts

            IEnumerable<JToken> tracts = items.Where(j => j["t"].ToString() == "0");
            var lstTracts = new List<Tract>();
            foreach (JToken t in tracts) {
                Tract item = DataHelper.JTokenToTract(t);
                lstTracts.Add(item);
            }
            p.Tracts = lstTracts;

            #endregion

            #region Load Rayons

            IEnumerable<JToken> rayons = items.Where(j => j["t"].ToString() == "1");
            var lstRayons = new List<Rayon>();
            foreach (JToken r in rayons) {
                Rayon item = DataHelper.JTokenToRayon(r);
                lstRayons.Add(item);
            }
            p.Rayons = lstRayons;

            #endregion

            #region Load Offres

            IEnumerable<JToken> offres = items.Where(j => j["t"].ToString() == "2");
            int filter = 100;
            int counter = 0;
            var lstOffresPartielles = new List<Offre>();

            foreach (JToken o in offres)
            {
                Offre item = DataHelper.JTokenToOffre(o);
                lstOffresPartielles.Add(item);
                counter++;
                if (counter == filter)
                    break;
            }
            p.OffresPartielles = lstOffresPartielles.ToList();

            #endregion

            p.Offres = new List<Offre>();
            //MOCK
            p.Offres.Add(new Offre { Id = 1234, Comment1 = "3 pour le prix de 2", NbrNeededForPromo = 3, NbrNeededToPay = 2 });

            return p;
        }

        /// <summary>
        /// Load all offres for a specific tract id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<Offre> LoadTractOffres(int id)
        {
            List<Offre> offres = new List<Offre>();

            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream fs = store.OpenFile(PROMO_FILE, FileMode.Open, FileAccess.Read))
                {
                    try
                    {
                        //using (var sw = new StreamWriter(fs))
                        //{
                        //    sw.Write(fs);
                        //}
                        string content = string.Empty;
                        fs.Position = 0;
                        
                        using (StreamReader reader = new StreamReader(fs))
                        {
                            //fs.Position = 0;
                            //var reader = new StreamReader(fs);
                            content = reader.ReadToEnd();
                        }

                        //using (var sr = new StreamReader(fs))
                        //{
                            //fs.
                            //var content = sr.ReadToEnd();
                            JObject json = JObject.Parse(content);

                            IEnumerable<JToken> items = json["data"].Where(j => j["c"].ToString() == "2" || j["c"].ToString() == "1");

                            IEnumerable<JToken> offresJson = items.Where(j => j["t"].ToString() == "2");
                            var tractOffres = new List<Offre>();

                            foreach (JToken o in offresJson) {

                                var tid = int.Parse(o["r"].ElementAt(15).ToString());
                                if (tid == id) {
                                    Offre item = DataHelper.JTokenToOffre(o);
                                    tractOffres.Add(item);
                                }
                            }
                            offres.AddRange(tractOffres);
                        //}
                    }
                    catch (Exception e) {
                        throw e;
                    }
                }
            }
            return offres;
        }

        /// <summary>
        /// Load all offre for a specific rayon
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<Offre> LoadRayonOffres(int id)
        {
            List<Offre> offres = new List<Offre>();

            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream fs = store.OpenFile(PROMO_FILE, FileMode.Open, FileAccess.Read))
                {
                    try
                    {
                        using (var sr = new StreamReader(fs))
                        {
                            var content = sr.ReadToEnd();
                            JObject json = JObject.Parse(content);

                            IEnumerable<JToken> items = json["data"].Where(j => j["c"].ToString() == "2" || j["c"].ToString() == "1");

                            IEnumerable<JToken> offresJson = items.Where(j => j["t"].ToString() == "2");
                            var tractOffres = new List<Offre>();

                            foreach (JToken o in offresJson)
                            {
                                JToken[] RayonIds = o["r"].ElementAt(1).ToArray();
                                if (RayonIds != null && RayonIds.Length > 0)
                                {
                                    var rids = new List<int>();
                                    foreach (JToken item in RayonIds)
                                    {
                                        var rid = int.Parse(item.ToString());
                                        if (rid == id) {
                                            Offre o2 = DataHelper.JTokenToOffre(o);
                                            tractOffres.Add(o2);
                                        }
                                    }
                                }
                            }
                            offres.AddRange(tractOffres);
                        }
                    }
                    catch (Exception e) {
                        throw e;
                    }
                }
            }
            return offres;
        }

        #region PropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(String name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        #endregion
    }
}
